package org.example;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;

public class CalculatorApp {

    private JFrame frame;
    private JTextField displayField, rpnField, prefixField, resultField;  // 新增 resultField 用于显示结果
    private JLabel rpnLabel, prefixLabel, resultLabel, rpnproLabel;  // 新增 rpnproLabel 用于显示后缀过程标签
    private JPanel buttonPanel;
    private String expression = "";
    private JTextArea processArea;  // 用于显示步骤信息的 TextArea

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new CalculatorApp().createAndShowGUI());
    }

    public void createAndShowGUI() {
        frame = new JFrame("计算器");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(700, 700);  // 扩展界面大小
        frame.setLayout(new BorderLayout(10, 10));
        // 设置窗口背景颜色
        frame.getContentPane().setBackground(new Color(240, 240, 240));
        // 顶部显示框
        displayField = createTextField(true);  // 只读显示框
        rpnField = createTextField(false);    // 只读后缀表达式框
        prefixField = createTextField(false); // 只读前缀表达式框
        resultField = createTextField(false); // 只读计算结果框
        // 创建前缀和后缀表达式的 JLabel
        rpnLabel = new JLabel("后缀表达式: ");
        rpnLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 18));
        rpnLabel.setForeground(Color.BLACK);
        prefixLabel = new JLabel("前缀表达式: ");
        prefixLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 18));
        prefixLabel.setForeground(Color.BLACK);
        // 创建后缀过程的 JLabel
        rpnproLabel = new JLabel("后缀过程: ");
        rpnproLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 18));
        rpnproLabel.setForeground(Color.BLACK);
        // 创建计算结果的 JLabel
        resultLabel = new JLabel("结果: ");
        resultLabel.setFont(new Font("Microsoft YaHei", Font.PLAIN, 18));
        resultLabel.setForeground(Color.BLACK);
        // 顶部面板
        JPanel topPanel = new JPanel();
        topPanel.setLayout(new BoxLayout(topPanel, BoxLayout.Y_AXIS));  // 垂直排列
        topPanel.setBackground(new Color(240, 240, 240));
        topPanel.add(displayField);
        topPanel.add(rpnLabel);
        topPanel.add(rpnField);
        topPanel.add(prefixLabel);
        topPanel.add(prefixField);
        topPanel.add(resultLabel);  // 添加“结果”标签
        topPanel.add(resultField);  // 添加结果显示框
        // 按钮面板
        buttonPanel = createButtonPanel();
        // 显示步骤信息的面板
        processArea = new JTextArea();
        processArea.setFont(new Font("Monospaced", Font.PLAIN, 14));  // 使用等宽字体
        processArea.setEditable(false);
        processArea.setBackground(Color.WHITE);
        processArea.setForeground(Color.BLACK);
        processArea.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
        processArea.setMargin(new Insets(5, 5, 5, 5));  // 添加内边距
        JScrollPane processScrollPane = new JScrollPane(processArea);
        processScrollPane.setPreferredSize(new Dimension(300, 600));  // 让步骤面板足够大
        // 设置右侧面板布局
        JPanel rightPanel = new JPanel();
        rightPanel.setLayout(new BorderLayout(10, 10));  // 使用 BorderLayout 布局
        rightPanel.setBackground(new Color(240, 240, 240));
        // 使用 BoxLayout 来让 rpnproLabel 和 processScrollPane 垂直对齐
        JPanel processPanel = new JPanel();
        processPanel.setLayout(new BoxLayout(processPanel, BoxLayout.Y_AXIS));  // 垂直排列
        processPanel.setBackground(new Color(240, 240, 240));
        processPanel.add(rpnproLabel);  // 后缀过程标签
        processPanel.add(Box.createVerticalStrut(10));  // 增加垂直间距
        processPanel.add(processScrollPane);  // 步骤信息显示区域
        // 将按钮面板和步骤信息面板添加到右侧面板
        rightPanel.add(buttonPanel, BorderLayout.CENTER);  // 将按钮面板放在中间
        rightPanel.add(processPanel, BorderLayout.EAST);  // 将步骤信息区域放在右侧
        // 添加到 frame
        frame.add(topPanel, BorderLayout.NORTH);
        frame.add(rightPanel, BorderLayout.CENTER);  // 将按钮和步骤信息区域放在中间
        frame.setVisible(true);

        // 添加键盘输入监听
        displayField.addKeyListener(new KeyAdapter() {
            @Override
            public void keyTyped(KeyEvent e) {
                char keyChar = e.getKeyChar();
                // 限制只允许输入数字、运算符、括号等字符
                if (Character.isDigit(keyChar) || "+-*/^()".indexOf(keyChar) != -1 || keyChar == KeyEvent.VK_BACK_SPACE) {
                    expression += keyChar;
                    displayField.setText(expression);
                }
                e.consume();  // 消费事件，防止输入无关字符
            }

            @Override
            public void keyPressed(KeyEvent e) {
                if (e.getKeyCode() == KeyEvent.VK_ENTER) {
                    // 按下回车键，触发等号操作
                    handleEqualAction();
                }
            }
        });
    }

    // 创建只读的 JTextField
    private JTextField createTextField(boolean isEditable) {
        JTextField textField = new JTextField();
        textField.setFont(new Font("Microsoft YaHei", Font.PLAIN, 24));  // 设置中文字体
        textField.setHorizontalAlignment(JTextField.RIGHT);
        textField.setBackground(Color.WHITE);
        textField.setForeground(Color.BLACK);
        textField.setBorder(BorderFactory.createLineBorder(Color.GRAY, 1));
        textField.setPreferredSize(new Dimension(100, 50));
        textField.setEditable(isEditable);  // 设置是否可编辑
        return textField;
    }

    private JPanel createButtonPanel() {
        JPanel panel = new JPanel();
        panel.setLayout(new GridLayout(6, 4, 10, 10));  // 增加按钮间隔
        panel.setBackground(new Color(240, 240, 240));
        // 定义按钮
        String[] buttons = {
                "7", "8", "9", "/",
                "4", "5", "6", "*",
                "1", "2", "3", "-",
                "0", ".", "=", "+",
                "AC", "Del", "(", ")",
                "^"
        };

        for (String text : buttons) {
            JButton button = new JButton(text);
            button.setFont(new Font("Microsoft YaHei", Font.PLAIN, 20));  // 设置中文字体
            button.setBackground(new Color(220, 220, 220));
            button.setForeground(Color.BLACK);
            button.setFocusPainted(false);
            button.setBorder(BorderFactory.createLineBorder(Color.GRAY));
            button.addActionListener(createButtonListener());
            panel.add(button);
        }

        return panel;
    }

    private ActionListener createButtonListener() {
        return new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String text = e.getActionCommand();

                if ("AC".equals(text)) {
                    expression = "";
                    displayField.setText("");  // 清空输入框
                    rpnField.setText("");      // 清空 RPN
                    prefixField.setText("");   // 清空前缀表达式
                    resultField.setText("");   // 清空结果框
                    updateProcessArea("");     // 清空过程区域
                } else if ("Del".equals(text)) {
                    if (expression.length() > 0) {
                        expression = expression.substring(0, expression.length() - 1);
                        displayField.setText(expression);
                    }
                } else if ("=".equals(text)) {
                    handleEqualAction();
                } else {
                    expression += text;
                    displayField.setText(expression);
                }
            }
        };
    }

    // 执行等号操作
    private void handleEqualAction() {
        try {
            Lexer lexer = new Lexer(expression);
            Parser parser = new Parser(lexer);
            double result = parser.expr();
            // 更新结果框
            resultField.setText(String.valueOf(result));
            // 生成逆波兰表达式
            RPNGenerator rpnGenerator = new RPNGenerator(expression);
            String rpn = rpnGenerator.generateRPN();
            rpnField.setText(rpn);
            // 生成前缀表达式
            PrefixGenerator prefixGenerator = new PrefixGenerator(expression);
            String prefix = prefixGenerator.generatePrefix();
            prefixField.setText(prefix);
            // 更新步骤过程
            updateProcessArea(rpnGenerator.getProcessLog());
            expression = String.valueOf(result);
        } catch (Exception ex) {
            displayField.setText("输入错误");
            rpnField.setText("");  // 清空 RPN
            prefixField.setText(""); // 清空前缀表达式
            resultField.setText(""); // 清空结果框
            updateProcessArea("输入错误"); // 显示错误信息
        }
    }

    // 更新显示过程的区域
    private void updateProcessArea(String log) {
        processArea.setText(log);
    }
}
